
#ifndef	__SINKER_FIFO_STORAGE_HPP_2010__
#define	__SINKER_FIFO_STORAGE_HPP_2010__

#include	<time.h>

#include	<vector>
#include	<map>
#include	<string>


#include	"storage.hpp"


#define	FS_MAX_PATH	512

#define	FS_CACHE_SIZE_DEFAULT	(1048576 * 32)

#define	FS_FLUSH_BUF_SIZE_DEFAULT	(1048576 * 8)

///////////////////////////////////////////////////////////////////////

struct	CacheItemHead
{
	int	m_iDataSize;
	int	m_iCacheItemSize;
};
typedef	struct CacheItemHead	CacheItemHead;
typedef	struct CacheItemHead	cache_item_head_t;

struct	CacheItem
{
public	:
	CacheItem() : m_iDataSize(0), m_iCacheItemSize(0) {}
	
public	:
	int	m_iDataSize;
	int	m_iCacheItemSize;
	char	m_szData[1];
};
typedef	struct CacheItem	CacheItem;
typedef	struct CacheItem	cache_item_t;
typedef	std::vector< cache_item_t* >	cache_item_list_t;

///////////////////////////////////////////////////////////////////////

struct	FifoStorageCell
{
public	:
	FifoStorageCell() : m_file(NULL), m_iSwitchCounter(0) {}
	
public	:
	char	m_szFileName[ FS_MAX_PATH ];
	FILE*	m_file;
	unsigned	m_iSwitchCounter;
	
	time_t	m_iSwitchTimeout;
	
	int		m_iLineCount;
	
	cache_item_list_t	m_cache;
};

///////////////////////////////////////////////////////////////////////

class	FifoStorage	: public ISinkStorage
{
public	:
	FifoStorage ( const char* pszConfigFile );
	virtual	~FifoStorage ();
	
	virtual	int		open ( void );
	virtual	int		close ( void );

	virtual	int		write ( unsigned iType, const void*	pvData, unsigned iDataSize );

	virtual	int		switchStorage ( bool bForce = false );
	
	void	setSwitchCountLimit ( unsigned iLimit ) { m_iSwitchCountLimit = iLimit; }
	unsigned	getSwitchCountLimit ( void ) const { return m_iSwitchCountLimit; }

	void	setSwitchSizeLimit ( unsigned iSliceSize ) { m_iSwitchSliceSize = iSliceSize; }
	unsigned	getSwitchSizeLimit ( void ) const { return m_iSwitchSliceSize; }
		
private	:
	int		loadConfig ( const char* pszConfigure );

public	:
	virtual	int		open ( int iType );
	virtual	int		close ( int iType );

protected	:
	virtual	FILE*	getFileHandle ( int iType );

private	:
	bool	flushCache ( void );
	cache_item_t*	allocateCache( int iDataSize );
		
	FifoStorageCell*	getStorageCell( int iType );
	
private	:
	bool	needSwitchBySize ( int iType );
	bool	needSwitchByCount ( int iType );
	bool	needSwitchBySize ( FifoStorageCell* pCell );
	bool	needSwitchByCount ( FifoStorageCell* pCell );
	bool	needSwitchByTimeout ( FifoStorageCell* pCell );
	
	int		countAndSwitchStorage ( int iType );
	int		switchStorage ( int iType, FifoStorageCell* pCell );
	
private	:
	std::string		m_strDataDir;
	std::string		m_strFifoList;
	
	unsigned	m_iSwitchCountLimit;
	unsigned	m_iSwitchTimeout;
	long		m_iSwitchSliceSize;
	
	int		m_iOutCacheSize;
	int		m_iOutCacheSizeFree;
	int		m_iOutCacheSizeUsed;
	char*	m_pszOutCache;

	bool	m_bCIDPrefix;
	bool	m_bDateSubdir;
    bool    m_bGZipFile;
	
	char	m_szSwitchSuffix[ 8 ];
		
	char*	m_pszSinkRoot;

	const char*	m_pszConfigFile;
	
	//std::string		m_strDataFile;
	//FILE*	m_file;
	//unsigned	m_iSwitchCounter;
	
	typedef	std::map< int, FifoStorageCell* >	map_storage_cell_t;
	map_storage_cell_t	m_mapStorageCell;
	
	int		m_iFlushBufSize;
	char*	m_pszFlushBuf;
};	/* class FifoStorage */


#endif	/* __SINKER_FIFO_STORAGE_HPP_2010__ */
